template<bool B, typename T>
class base_iterator
{
public:
    typedef base_iterator self_type;
    typedef typename std::conditional<B , const T, T>::type value_type;
    typedef typename std::conditional<B , const T&, T&>::type reference;
    typedef typename std::conditional<B , const T*, T*>::type pointer;
    typedef int difference_type;
    typedef std::bidirectional_iterator_tag iterator_category;
    self_type(pointer ptr) : ptr_(ptr), rowCount(0), colCount(0), pRowCount(0), pColCount(0), rowOffset(0), colOffset(0), currentIndex(0), isChild(false) { }
    self_type(pointer ptr, int rows, int columns, int parentRows, int parentCols, int rowOffset, int colOffset, int currentIndex) : ptr_(ptr), rowCount(rows), colCount(columns), pRowCount(parentRows), pColCount(parentCols), rowOffset(rowOffset), colOffset(colOffset), currentIndex(currentIndex), isChild(true)
    {
        position = CalculateChildPosition();
    }
    reference operator*() { return *ptr_; }
    pointer operator->() { return ptr_; }
    bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
    bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
    bool operator< (const self_type& rhs) { return ptr_ < rhs.ptr_; }
    bool operator> (const self_type& rhs) { return ptr_ > rhs.ptr_; }
    self_type operator++() { self_type i = *this; move(1); return i; }
    self_type operator++(int junk) { move(1); return *this; }
    self_type operator--() { self_type i = *this; move(-1); return i; }
    void operator+=(const T n)  { self_type i = *this; move(n); }
    void operator-=(const T n)  { self_type i = *this; move(-n); }
private:
    pointer ptr_;
    int rowCount;
    int colCount;
    int pRowCount;
    int pColCount;
    int rowOffset;
    int colOffset;
    bool isChild;
    int currentIndex;
    int position;

    int CalculateChildIndex(int row, int column) const
    {
        return (row + rowOffset) * pColCount + column + colOffset;
    }

    int CalculateChildPosition() const
    {
        int row = currentIndex / pColCount - rowOffset;
        int col = currentIndex % pColCount - colOffset;
        return row * colCount + col;
    }

    void move(int shift)
    {
        if (!isChild)
        {
            ptr_ += shift;
            return;
        }

        position += shift;

        int newRow = position / colCount;
        int newCol = position % colCount;
        int newIndex = CalculateChildIndex(newRow, newCol);
        int difference = newIndex - currentIndex;

        ptr_ += difference;
        currentIndex += difference;
    }
};